﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Gueei.Gallery.Core.DisplayProfiles;
using Gueei.Gallery.Core.Entities;
using Gueei.Gallery.Core.Repositories;

namespace Gueei.Gallery.Core.Services
{
	/// <summary>
	/// Cache thumbnail images in local file system.
	/// TODO: Add support to control cache size and removal mechanism
	/// This is done base on Default Image Service
	/// </summary>
	public class CachedThumbnailImageService:IImageService
	{
		// Actual worker on most operations
		private IImageService _imageService;

		private readonly IImageRepository _imageRepo;
		private readonly IFileRepository _fileRepo;
		private readonly ITagRepository _tagRepo;
		private readonly string _localCachePath;

		public CachedThumbnailImageService(IImageRepository imageRepo, IFileRepository fileRepo, ITagRepository tagRepo, string localCachePath)
		{
			_imageRepo = imageRepo;
			_fileRepo = fileRepo;
			_tagRepo = tagRepo;
			_localCachePath = localCachePath;

			// This should throw something if dir is not usable
				Directory.CreateDirectory(localCachePath);

			_imageService = new DefaultImageService(imageRepo, fileRepo, tagRepo);
		}

		public Entities.Image SaveNewImage(string tags, string name, string description, string originalFileName, string mimeType, Entities.User creator, System.IO.FileInfo file)
		{
			return _imageService.SaveNewImage(tags, name, description, originalFileName, mimeType, creator, file);
		}

		public Entities.Image SaveNewImage(string tags, string name, string description, string originalFileName, string mimeType, Entities.User creator, byte[] data)
		{
			return _imageService.SaveNewImage(tags, name, description, originalFileName, mimeType, creator, data);
		}

		public Entities.Image GetImage(Guid id)
		{
			return _imageService.GetImage(id);
		}

		public byte[] GetImageFile(Guid id)
		{
			return _imageService.GetImageFile(id);
		}

		public byte[] GetImageFile(Guid id, DisplayProfileBase profile)
		{
			if (!profile.NeedCache) return _imageService.GetImageFile(id, profile);

			// This is the serious stuff!
			// Look for the local cache
			if (File.Exists(GetFileNameForImageCache(id, profile)))
			{
				return File.ReadAllBytes(GetFileNameForImageCache(id, profile));
			}
			else
			{
				var data = _imageService.GetImageFile(id, profile);
				Directory.CreateDirectory(GetDirForProfile(profile));
				File.WriteAllBytes(GetFileNameForImageCache(id, profile), data);
				return data;
			}
		}

		private string GetDirForProfile(DisplayProfileBase profile)
		{
			return Path.Combine(_localCachePath, profile.Name);
		}

		private string GetFileNameForImageCache(Guid id, DisplayProfileBase profile)
		{
			return Path.Combine(GetDirForProfile(profile), id.ToString());
		}

		public bool ImageExists(Guid id)
		{
			return _imageService.ImageExists(id);
		}


		private void CleanupCachedImage(Guid id)
		{
			foreach(var filename in 
				Directory.EnumerateFiles(_localCachePath, id.ToString(), SearchOption.AllDirectories))
			{
				File.Delete(filename);
			}
		}

		public Image ApplyFilterAndSaveImage(Guid id, Filters.ImageFilter filter)
		{
			CleanupCachedImage(id);
			return _imageService.ApplyFilterAndSaveImage(id, filter);
		}


		public Image UpdateImage(Guid id, string tags, string name, string description, User modifiedBy)
		{
			return _imageService.UpdateImage(id, tags, name, description, modifiedBy);
		}
	}
}
